#include "asio_header.h"
#include "asio_Server.h"
#include "asio_NetworkHandler.h"
#include "ServerHandler.h"

namespace XGC
{
	namespace net
	{
		asio_ServerBase::asio_ServerBase( _uint32 nTimerInvent )
			: acceptor_( service_, ip::tcp::v4() )
			, timer_invent( nTimerInvent )
		{
		}

		asio_ServerBase::~asio_ServerBase(void)
		{
			acceptor_.close();
		}

		bool asio_ServerBase::StartServer( const char *address, short port )
		{
			system::error_code ec;
			ip::address_v4 addr = ip::address_v4::from_string( address, ec );
			if( ec )
				return false;

			acceptor_.bind( ip::tcp::endpoint( addr, port ), ec );
			if( ec )
				return false;

			acceptor_.listen( 10, ec );
			if( ec )
				return false;

			for( int i = 0; i < 10; ++i )
			{
				post_accept();
			}

			SYSTEM_INFO SystemInfo;
			::GetSystemInfo( &SystemInfo );

			for( DWORD i = 0; i < SystemInfo.dwNumberOfProcessors * 2 + 2; ++i )
				workthreads_.push_back( shared_ptr<thread>( new thread( bind( &io_service::run, &service_ ) ) ) );

			return true;
		}

		void asio_ServerBase::StopServer()
		{
			for( size_t i = 0; i < workthreads_.size(); ++ i )
			{
				service_.post( bind(&asio_ServerBase::handle_stop, this) );
			}

			for( size_t i = 0; i < workthreads_.size(); ++ i )
			{
				workthreads_[i]->join();
			}
		}

		void asio_ServerBase::handle_accept( asio_SocketPtr pSocket, const system::error_code& error)
		{
			if (!error)
			{
				pSocket->accpet();
				post_accept();
			}
		}

		void asio_ServerBase::handle_stop()
		{
			system::error_code ec;
			acceptor_.close( ec );
			asio_HandlerManager::Instance().CloseAll();
		}
	}

	//----------------------------------------------------------------
	namespace net
	{
		//////////////////////////////////////////////////////////////////////////
		// Server

		asio_Server::asio_Server( IMessageQueue *pMessageQueue, _uint32 nTimerInvent )
			: asio_ServerBase( nTimerInvent )
			, m_pMessageQueue( pMessageQueue )
		{

		}

		asio_Server::~asio_Server()
		{

		}

		void asio_Server::post_accept()
		{
			asio_SocketPtr pSocket( new asio_Socket(service_, new CServerHandler( m_pMessageQueue ), timer_invent ) );
			acceptor_.async_accept(pSocket->socket(), boost::bind(&asio_Server::handle_accept, this, pSocket, asio::placeholders::error) );
		}

		//////////////////////////////////////////////////////////////////////////
		// ServerEx
		asio_ServerEx::asio_ServerEx( create_handler_func call, long_ptr param, _uint32 nTimerInvent )
			: asio_ServerBase( nTimerInvent )
			, call_( call )
			, param_( param )
		{
		}

		asio_ServerEx::~asio_ServerEx(void)
		{
		}

		void asio_ServerEx::post_accept()
		{
			asio_SocketPtr pSocket(new asio_Socket(service_, call_( param_ ), timer_invent ) );
			acceptor_.async_accept(pSocket->socket(), boost::bind(&asio_ServerEx::handle_accept, this, pSocket, asio::placeholders::error));
		}
	}

}